/**
 * 初始有一个球序列，然后用一个子弹球去撞任意位置。
 * 只要相同的球大于等于2个这一段就会消失并得分，两边剩下的球会汇合，如果汇合的新段大于等于2，会继续反复这个过程
 * 问最大得分是多少。
 * 首先将球序列unique一下，可以看到每个位置能够引发的合并其实就是最长回文半径
 * 然后根据每一段球的数量计算出分数，求最大即可
 */
#include <bits/stdc++.h>
using namespace std;

using llt = long long;
using vi = vector<int>;
using Real = long double;

template<typename IT = const char *>
struct Manacher{

using vi = vector<int>;
using pii = pair<int, int>;

/// 从begin开始，一共n个
Manacher(IT begin, int n){
    tmp.reserve(n + n + 3);
    tmp.emplace_back(-2);
    tmp.emplace_back(-1);

	auto it = begin;
    for(int i=0;i<n;++i){
        assert(*it >= 0);
        tmp.emplace_back(*it++);
        tmp.emplace_back(-1);
    }
    tmp.emplace_back(-3);
    assert(tmp.size() == n + n + 3);

    r.assign(tmp.size(), 0);
    r[0] = r[1] = 1;

    int x = 1, total = r.size(), k;
    while(x < total){
        for(k=1;k<r[x];++k){
            if(k + r[x - k] == r[x]) break;
            r[x + k] = min(r[x - k], r[x] - k);
        }

        /// 半径至少是1或者r[x - k]
        r[x + k] = k == r[x] ? 1 : r[x - k];
        if((x += k) >= total - 1) break;
        while(tmp[x + r[x]] == tmp[x - r[x]]) ++r[x];
    }

    auto & ret = result.first;
    auto & start = result.second;
    for(int t,i=0;i<total;++i){
        t = r[i] - 1;
        if(ret < t) start = (i - (ret = t)) >> 1;
    }

    return;
}

const pii & get() const {return result;}

vi tmp; // 临时数组
vi r; // 回文半径数组
pii result; // <最长回文长度, 第一个开始的地方>, 从0开始编号

};

int N, M;
string S;
map<char, llt> Fen;
vector<pair<char, llt>> Vec;
vector<char> Ch;
vector<llt> Sum;

llt proc(){
    Vec.reserve(N);
    Ch.reserve(N);
    int k = 0;
    while(1){
        int o = 0;
        while(k < N and S[k] == S[k + o]) o += 1;

        Vec.emplace_back(S[k], o);
        Ch.emplace_back(S[k]);
        if((k +=o) == N) break;
    }
    
    int n = Ch.size();
    Manacher<vector<char>::iterator> mana(Ch.begin(), n);
    Sum.reserve(n);
    Sum.emplace_back(Vec[0].second * Fen[Vec[0].first]);
    for(int i=1;i<n;++i){
        Sum.emplace_back(Sum.back() + Vec[i].second * Fen[Vec[i].first]);
    }

    
    llt ans = 0;
    for(int i=0;i<n;++i){
        int p = (i + 1) * 2;
        int r = mana.r[p];
        int t = r / 2;
        if(r & 1) t += 1;
        int left = i - t + 1;
        int right = i + t - 1;
        assert(0 <= left and left <= right and right < n);
        auto fenshu = Sum[right];
        if(left) fenshu -= Sum[left - 1];
        fenshu += Fen[Ch[i]];
        ans = max(ans, fenshu);
    }
    return ans;
}

void work(){
    cin >> N >> M >> S;
    for(int i=0;i<M;++i){
        char ch;
        llt t;
        cin >> ch >> t;
        Fen[ch] = t;
    }
    cout << proc() << endl;
    return;
}

int main(){
#ifndef ONLINE_JUDGE
    freopen("z.txt", "r", stdin);
#endif
    ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
    int nofkase = 1;
    // cin >> nofkase;
    while(nofkase--) work();
    return 0;
}
